{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "udacity-cs344-hw3",
      "version": "0.3.2",
      "provenance": [],
      "collapsed_sections": [],
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/depctg/udacity-cs344-colab/blob/master/notebook/udacity_cs344_hw3.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "metadata": {
        "id": "hse6gSyUS5ka",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "# Homework 3 for Udacity CS344 Course, Intro to Parallel Programming\n",
        "# clone the code repo,\n",
        "!git clone https://github.com/depctg/udacity-cs344-colab\n",
        "!pip install git+git://github.com/depctg/nvcc4jupyter.git\n",
        "\n",
        "# load cuda plugin\n",
        "%config NVCCPluginV2.static_dir = True\n",
        "%config NVCCPluginV2.relative_dir = \"udacity-cs344-colab/src/HW3\"\n",
        "%load_ext nvcc_plugin\n",
        "\n",
        "# change to work directory, generate makefiles\n",
        "!mkdir udacity-cs344-colab/build\n",
        "%cd udacity-cs344-colab/build\n",
        "!cmake ../src"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "3vA0JP15TORh",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "%%cuda --name student_func.cu\n",
        "\n",
        "/* Udacity Homework 3\n",
        "   HDR Tone-mapping\n",
        "\n",
        "  Background HDR\n",
        "  ==============\n",
        "\n",
        "  A High Dynamic Range (HDR) image contains a wider variation of intensity\n",
        "  and color than is allowed by the RGB format with 1 byte per channel that we\n",
        "  have used in the previous assignment.\n",
        "\n",
        "  To store this extra information we use single precision floating point for\n",
        "  each channel.  This allows for an extremely wide range of intensity values.\n",
        "\n",
        "  In the image for this assignment, the inside of church with light coming in\n",
        "  through stained glass windows, the raw input floating point values for the\n",
        "  channels range from 0 to 275.  But the mean is .41 and 98% of the values are\n",
        "  less than 3!  This means that certain areas (the windows) are extremely bright\n",
        "  compared to everywhere else.  If we linearly map this [0-275] range into the\n",
        "  [0-255] range that we have been using then most values will be mapped to zero!\n",
        "  The only thing we will be able to see are the very brightest areas - the\n",
        "  windows - everything else will appear pitch black.\n",
        "\n",
        "  The problem is that although we have cameras capable of recording the wide\n",
        "  range of intensity that exists in the real world our monitors are not capable\n",
        "  of displaying them.  Our eyes are also quite capable of observing a much wider\n",
        "  range of intensities than our image formats / monitors are capable of\n",
        "  displaying.\n",
        "\n",
        "  Tone-mapping is a process that transforms the intensities in the image so that\n",
        "  the brightest values aren't nearly so far away from the mean.  That way when\n",
        "  we transform the values into [0-255] we can actually see the entire image.\n",
        "  There are many ways to perform this process and it is as much an art as a\n",
        "  science - there is no single \"right\" answer.  In this homework we will\n",
        "  implement one possible technique.\n",
        "\n",
        "  Background Chrominance-Luminance\n",
        "  ================================\n",
        "\n",
        "  The RGB space that we have been using to represent images can be thought of as\n",
        "  one possible set of axes spanning a three dimensional space of color.  We\n",
        "  sometimes choose other axes to represent this space because they make certain\n",
        "  operations more convenient.\n",
        "\n",
        "  Another possible way of representing a color image is to separate the color\n",
        "  information (chromaticity) from the brightness information.  There are\n",
        "  multiple different methods for doing this - a common one during the analog\n",
        "  television days was known as Chrominance-Luminance or YUV.\n",
        "\n",
        "  We choose to represent the image in this way so that we can remap only the\n",
        "  intensity channel and then recombine the new intensity values with the color\n",
        "  information to form the final image.\n",
        "\n",
        "  Old TV signals used to be transmitted in this way so that black & white\n",
        "  televisions could display the luminance channel while color televisions would\n",
        "  display all three of the channels.\n",
        "\n",
        "\n",
        "  Tone-mapping\n",
        "  ============\n",
        "\n",
        "  In this assignment we are going to transform the luminance channel (actually\n",
        "  the log of the luminance, but this is unimportant for the parts of the\n",
        "  algorithm that you will be implementing) by compressing its range to [0, 1].\n",
        "  To do this we need the cumulative distribution of the luminance values.\n",
        "\n",
        "  Example\n",
        "  -------\n",
        "\n",
        "  input : [2 4 3 3 1 7 4 5 7 0 9 4 3 2]\n",
        "  min / max / range: 0 / 9 / 9\n",
        "\n",
        "  histo with 3 bins: [4 7 3]\n",
        "\n",
        "  cdf : [4 11 14]\n",
        "\n",
        "\n",
        "  Your task is to calculate this cumulative distribution by following these\n",
        "  steps.\n",
        "\n",
        "*/\n",
        "\n",
        "#include \"utils.h\"\n",
        "\n",
        "void your_histogram_and_prefixsum(const float* const d_logLuminance,\n",
        "                                  unsigned int* const d_cdf,\n",
        "                                  float &min_logLum,\n",
        "                                  float &max_logLum,\n",
        "                                  const size_t numRows,\n",
        "                                  const size_t numCols,\n",
        "                                  const size_t numBins)\n",
        "{\n",
        "  //TODO\n",
        "  /*Here are the steps you need to implement\n",
        "    1) find the minimum and maximum value in the input logLuminance channel\n",
        "       store in min_logLum and max_logLum\n",
        "    2) subtract them to find the range\n",
        "    3) generate a histogram of all the values in the logLuminance channel using\n",
        "       the formula: bin = (lum[i] - lumMin) / lumRange * numBins\n",
        "    4) Perform an exclusive scan (prefix sum) on the histogram to get\n",
        "       the cumulative distribution of luminance values (this should go in the\n",
        "       incoming d_cdf pointer which already has been allocated for you)       */\n",
        "\n",
        "\n",
        "}"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "sSAnpiE2nL1T",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "# make the cuda project\n",
        "!make HW3\n",
        "print(\"\\n====== RESULT OF HW3 =======\\n\")\n",
        "!bin/HW3 ../src/HW3/memorial_png_large.gold"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "2cGKiWj_n-Na",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        "# plot output images\n",
        "import matplotlib.pyplot as plt\n",
        "_,ax = plt.subplots(2,2, dpi=150)\n",
        "\n",
        "ax[0][0].imshow(plt.imread(\"../src/HW3/memorial_raw_large.png\"))\n",
        "ax[0][0].set_title(\"original\")\n",
        "ax[0][0].grid(False)\n",
        "\n",
        "ax[0][1].imshow(plt.imread(\"HW3_output.png\"))\n",
        "ax[0][1].set_title(\"output\")\n",
        "ax[0][1].grid(False)\n",
        "\n",
        "ax[1][0].imshow(plt.imread(\"HW3_reference.png\"))\n",
        "ax[1][0].set_title(\"reference\")\n",
        "ax[1][0].grid(False)\n",
        "\n",
        "ax[1][1].imshow(plt.imread(\"HW3_differenceImage.png\"))\n",
        "ax[1][1].set_title(\"difference\")\n",
        "ax[1][1].grid(False)\n",
        "\n",
        "plt.show()"
      ],
      "execution_count": 0,
      "outputs": []
    }
  ]
}